package com.example.study.controller;

import com.example.study.commen.email.EmailUtil;
import com.example.study.config.JsonResult;
import com.example.study.config.redis.RedisUtil;
import com.example.study.config.shiro.JwtUtil;
import com.example.study.controller.dto.LoginDTO;
import com.example.study.plus.mybatis_plus.entity.Friend;
import com.example.study.plus.mybatis_plus.entity.TokenUser;
import com.example.study.plus.mybatis_plus.entity.User;
import com.example.study.plus.mybatis_plus.service.FriendService;
import com.example.study.plus.mybatis_plus.service.TokenUserService;
import com.example.study.plus.mybatis_plus.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

@CrossOrigin//同源问题
@RestController
@RequestMapping("/study")
@Slf4j
@Api(description = "新版本登录注册")
public class ShiroController {

    @Autowired
    UserService userService;
    @Autowired
    TokenUserService tokenUserService;
    @Resource
    FriendService friendService;
    @Resource
    RedisUtil redisUtil;

    @ApiOperation(value = "登陆", notes = "参数:用户名 密码")
    @PostMapping(value = "/sys/login")
    @Transactional
    public Map<String, Object> login(@RequestBody @Validated LoginDTO loginDTO, BindingResult bindingResult) {
        Map<String, Object> result = new HashMap<>();
        if (bindingResult.hasErrors()) {
            result.put("status", 400);
            result.put("msg", Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
            return result;
        }
        String username = loginDTO.getUsername();
        String password = loginDTO.getPassword();
        //用户信息

        User user = userService.getUserByUsername(username);

        if (user == null) {
            result.put("status", 400);
            result.put("msg", "账号不存在");
            return result;
        }
        //账号不存在、密码错误
        if (!user.getPassword().equals(password)) {
            result.put("status", 400);
            result.put("msg", "账号或密码有误");
        } else {
            //生成token，并保存到数据库
            String token = JwtUtil.sign(user.getName(), user.getPassword());
//            log.info("token:  "+token.length()+"  \n");
            tokenUserService.saveVoucher(user.getId(), user.getName(), token);
            result.put("status", 200);
            result.put("userId", user.getId());
            result.put("userName", user.getName());
            result.put("msg", "登陆成功");
            result.put("token", token);
        }
        return result;
    }

    @ApiOperation(value = "登出", notes = "参数:token")
    @PostMapping("/sys/logout")
    public Map<String, Object> logout(@RequestHeader("token") String token, @ApiParam("用户名") @RequestParam String username) {
        Map<String, Object> result = new HashMap<>();
        tokenUserService.delVoucher(token);
        result.put("status", 200);
        result.put("msg", "您已安全退出系统");
        return result;
    }

    @ApiOperation(value = "测试", notes = "参数:token")
    @PostMapping("/sys/test")
    public Map<String, Object> test(@RequestHeader("token") String token, @RequestParam String msg) {
        Map<String, Object> result = new HashMap<>();
        result.put("status", "你已经登录");
        result.put("msg", msg);
        return result;
    }

    @ApiOperation(value = "注册")
    @PostMapping("/sys/register")
    @Transactional
    public Map<String, Object> register(@RequestParam String name, @RequestParam String password, @RequestParam String emailAddress, @RequestParam String verificationCode) {
        //打印当前接口中上传的参数

        log.info("注册接口收到: " + name + " " + password + " " + emailAddress + " " + verificationCode);


        Map<String, Object> result = new HashMap<>();
        if (!redisUtil.hasKey(emailAddress)) {
            result.put("status", 101);
            result.put("msg", "验证码已过期");
            return result;
        }
        if (!redisUtil.get(emailAddress).equals(verificationCode)) {
            result.put("status", 101);
            result.put("msg", "验证码错误");
            return result;
        }
        int register = userService.register(name, password, emailAddress);
        result.put("status", register);
        result.put("msg", "注册成功");
        return result;
    }

    @PostMapping("/sys/getUserList")
    @ApiOperation(value = "查询用户列表")
    public JsonResult<List<String>> getUserList(@ApiParam("查询账户") @RequestParam String name, HttpServletRequest request) {
        //缓存向应用
//        ServletContext application = request.getServletContext();
//        List<String> userList = (List<String>) application.getAttribute("userList");

        log.info("session: " + "\n" + request.getSession().getId() + "\n" + request.getSession().getCreationTime());
        List<String> userList = userService.getUserList();
        return new JsonResult<>(userList);
    }

    @PostMapping("/sys/changePassword")
    @ApiOperation(value = "修改密码")
    public JsonResult<String> changePassword(@RequestHeader("token") String token, @ApiParam("用户名") @RequestParam String name, @ApiParam("新密码") @RequestParam String pass) {
        int i = userService.changePassword(name, pass);
        if (i > 0) {
            return new JsonResult<>("修改成功");
        } else {
            return new JsonResult<>("修改失败");
        }
    }

    @PostMapping("/sys/applyForFriends")
    @ApiOperation(value = "申请好友")
    public JsonResult<String> applyForFriends(@ApiParam("申请用户id") @RequestParam Long fromUserID, @ApiParam("被申请用户id") @RequestParam Long toUserId) {
        int result = friendService.applyForFriends(fromUserID, toUserId);
        if (result == 1) {
            return new JsonResult<>("申请好友已发送");
        } else if (result == 201) {
            return new JsonResult<>("对方昵称不存在");
        } else if (result == 202) {
            return new JsonResult<>("已经是好友");
        } else if (result == 203) {
            return new JsonResult<>("已经发送过");
        } else if (result == 205) {
            return new JsonResult<>("已收到对方发的申请");
        } else if (Objects.equals(fromUserID, toUserId)) {
            return new JsonResult<>(101,"不能发给自己");
        } else {
            return new JsonResult<>("业务异常");
        }
    }

    @PostMapping("/sys/queryTheListOfApplications")
    @ApiOperation(value = "查询当前用户发出的申请列表")
    public JsonResult<List<User>> queryTheListOfApplications(@ApiParam("当前用户UID") @RequestParam Long userId) {
        List<Friend> list = friendService.queryTheListOfApplications(userId);
        List<User> nameList = new ArrayList<>(list.size());
        for (Friend friend : list) {
            nameList.add(userService.getUserByUserId2(friend.getAcceptId()));
        }
        return new JsonResult<>(nameList);
    }

    @PostMapping("/sys/enquireAboutReceivingApplications")
    @ApiOperation(value = "查询收到的申请列表")
    public JsonResult<List<User>> enquireAboutReceivingApplications(@ApiParam("当前用户UID") @RequestParam Long userId) {
        List<Friend> list = friendService.enquireAboutReceivingApplications(userId);
        List<User> nameList = new ArrayList<>(list.size());
        for (Friend friend : list) {
            nameList.add(userService.getUserByUserId2(friend.getFromId()));
        }
        return new JsonResult<>(nameList);
    }

    @PostMapping("/sys/agreeToApply")
    @ApiOperation(value = "同意申请")
    public JsonResult<String> agreeToApply(@ApiParam("当前用户UID") @RequestParam Long myID, @ApiParam("申请人-用户UID") @RequestParam Long fromUserId) {
        int i = friendService.agreeToApply(myID, fromUserId);
        if (i == 1) {
            return new JsonResult<>(200, "已同意");
        } else {
            return new JsonResult<>(101, "发生异常");
        }
    }

    @PostMapping("/sys/queryYourFriendsList")
    @ApiOperation(value = "查询好友列表")
    public JsonResult<List<User>> queryYourFriendsList(@ApiParam("当前用户UID") @RequestParam Long myID) {
        List<User> users = friendService.queryYourFriendsList(myID);
        log.info("好友列表4" + users);
        return new JsonResult<>(users);
    }

    @PostMapping("/sys/deleteAFriend")
    @ApiOperation(value = "删除好友")
    public JsonResult<String> deleteAFriend(@ApiParam("当前用户UID") @RequestParam Long myID, @ApiParam("申请人-用户UID") @RequestParam Long fromUserId) {
        int i = friendService.deleteAFriend(myID, fromUserId);
        if (i == 1) {
            return new JsonResult<>(200, "删除成功");
        } else {
            return new JsonResult<>(101, "发生异常");
        }
    }

    @Resource
    private RabbitTemplate rabbitTemplate;

    public void xx() {

    }


    @ApiOperation("发送邮箱验证码")
    @PostMapping("/sendEmail")
    public JsonResult<String> sendEmail(@ApiParam("邮箱地址") @RequestParam("emailAddress") String emailAddress) {
        JsonResult<String> jsonResult = new JsonResult<>();

        if (emailAddress.isEmpty()) {
            jsonResult.message = "邮箱为空";
            jsonResult.code = 101;
            return jsonResult;
        }
        Random random = new Random();
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            code.append(random.nextInt(10));//生成0-9的随机数，并循环生成6位
        }
        try {
            EmailUtil.sendCode(String.valueOf(code), emailAddress);

            if (redisUtil.hasKey(emailAddress)) {
                jsonResult.message = "请60秒后重试";
                jsonResult.code = 101;
            } else {
                redisUtil.set(emailAddress, code, 60);
                jsonResult.message = "发送成功";
            }
        } catch (Exception e) {
            jsonResult.message = "发送失败";
            jsonResult.code = 101;
            throw new RuntimeException(e);
        }
        return jsonResult;
    }

    @ApiOperation("根据昵称查询用户")
    @PostMapping("/queryUsersBasedOnNickname")
    public JsonResult<User> queryUsersBasedOnNickname(@ApiParam("昵称") @RequestParam("userName") String userName) {
        User user = userService.getUserByUsername2(userName);
        if (null == user) {
            return new JsonResult<>(null, "查无此人");
        }
        return new JsonResult<>(user);
    }

    @ApiOperation("模糊搜索")
    @PostMapping("/fuzzySearchForUsers")
    public JsonResult<List<User>> fuzzySearchForUsers(@ApiParam("userId") @RequestParam("userId") long userId, @ApiParam("昵称") @RequestParam("userName") String userName) {
        List<User> users = userService.fuzzySearchForUsers(userId,userName);

        return new JsonResult<>(users);
    }

    @ApiOperation("登录是否有效")
    @PostMapping("/whetherTheLoginIsValid")
    public JsonResult<Boolean> whetherTheLoginIsValid(@ApiParam("userId") @RequestParam("userId") long userId, @RequestHeader("token") String token) {
        JsonResult<Boolean> result = new JsonResult<>();
        User user = userService.getUserByUserId(userId);
        if (null == user) {
            result.code = 300;
            result.data = false;
            result.message = "用户不存在";
            return result;
        }
        log.info(user.toString());
        TokenUser tokenUser = tokenUserService.findTokenByUserName(user.getName());

        if (null == tokenUser) {
            result.code = 300;
            result.data = false;
            result.message = "没有登录信息";
            return result;
        }

        if (!token.equals(tokenUser.getToken())) {
            result.code = 300;
            result.data = false;
            result.message = "已被他人登录";
            return result;
        }
        log.info(tokenUser.getToken() + "\n" + token);

        if (JwtUtil.verify(token, user.getName(), user.getPassword())) {
            result.code = 200;
            result.data = true;
            result.message = "已登录";
        } else {
            result.code = 300;
            result.data = false;
            result.message = "登录已过期";
        }

        return result;
    }
}
